package com.xxy.crm;

import com.alibaba.fastjson.JSON;
import com.xxy.crm.base.ResultInfo;
import com.xxy.crm.exceptions.AuthException;
import com.xxy.crm.exceptions.NoLoginException;
import com.xxy.crm.exceptions.ParamsException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
    /**
     * ⽅法返回值类型
     * 视图
     * JSON
     * 如何判断⽅法的返回类型：
     * 如果⽅法级别配置了 @ResponseBody 注解，表示⽅法返回的是JSON；
     * 反之，返回的是视图⻚⾯
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        /**
         * 判断异常类型
         * 如果是未登录异常，则先执⾏相关的拦截操作
         */
        if (ex instanceof NoLoginException){
            // 如果捕获的是未登录异常，则重定向到登录⻚⾯
            ModelAndView mv = new ModelAndView("redirect:/index");
            return mv;
        }

        //设置默认异常处理
        ModelAndView modelAndView = new ModelAndView("error");
        //设置异常信息
        modelAndView.addObject("code",500);
        modelAndView.addObject("msg","异常异常，请重试...");

        //判断HandlerMethod
        if (handler instanceof HandlerMethod){
            //类型转换
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取方法上的@ResponseBody注解对象
            ResponseBody responseBody = handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);
            //判断responseBody是否为空，如果为空，返回的是视图，不为空返回的是数据
            if (responseBody ==null){
                //返回视图
                //判断异常类型
                if (ex instanceof ParamsException){
                    ParamsException p = (ParamsException) ex;
                    //设置异常信息
                    modelAndView.addObject("code",p.getCode());
                    modelAndView.addObject("msg",p.getMsg());
                }else if (ex instanceof AuthException) {
                    AuthException p = (AuthException) ex;
                    //设置异常信息
                    modelAndView.addObject("code", p.getCode());
                    modelAndView.addObject("msg", p.getMsg());
                }
                return modelAndView;
            }else {
                //返回的就是数据类型
                //设置默认的异常处理
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setCode(500);
                resultInfo.setMsg("异常异常，请重试");

                //判断异常类型是否是自定义异常
                if (ex instanceof ParamsException){
                    ParamsException p = (ParamsException) ex;
                    resultInfo.setCode(p.getCode());
                    resultInfo.setMsg(p.getMsg());
                }else if (ex instanceof AuthException) {
                    AuthException p = (AuthException) ex;
                    resultInfo.setCode(p.getCode());
                    resultInfo.setMsg(p.getMsg());
                }

                //设置响应类型以及编码格式
                response.setContentType("application/json;charset=UTF-8");
                //得到字符输出流
                PrintWriter out = null;
                try {
                    //得到输出流
                    out = response.getWriter();
                    //讲返回的对象转为json格式
                    String json = JSON.toJSONString(resultInfo);
                    out.write(json);
                }catch (IOException e){
                    e.printStackTrace();
                }finally {
                    //如果对象不为空，则关闭
                    if(out !=null){
                        out.close();
                    }
                }
                return null;
            }
        }
        return modelAndView;
    }
}

